package com.feib.stms.crypto;


/*
 * @(#)DES.java
 *
 * Copyright (c) 2004 HiTRUST Incorporated. All rights reserved.
 *
 * Modify History:
 *  v1.00, 2004/07/20, Jackie Yang
 *   1) First release
 *
 */

/**
 * Encryption & decryption of DES algorithm.
 *
 * @author  Jackie Yang
 * @version 1.00, 2004/07/20
 */

//package tw.bankpro.util.upload;

import java.math.*; 
 
public class DES {
	/**
	 * Encrypt data using DES key in ECB mode with PKCS5 padding.
	 * The key must be a  byte array in 8/16/24 length.
	 * The returned encrypted data will padding to times of 8 length
	 * according to PKCS5 padding algorithm.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be encryped.
	 * @return  The encrypted data byte array
	 */
	 
	public static String encryptData(String sKey, String sData) {
		if (sKey != null && sData != null){
			if (!sKey.equals("") && !sData.equals("")){
				return toHexString(encryptData(sKey.getBytes(), sData.getBytes()));	
			}else{
				return sData;
			}    	
		}else{
			return "";
		}    	
	}
	 
	public static byte[] encryptData(byte[] key, byte[] data) {
		// ECB mode
		return encryptData(key, data, 'E');
	}

	/**
	 * Encrypt data using DES key in given mode with PKCS5 padding.
	 * The key must be a  byte array in 8/16/24 length.
	 * The returned encrypted data will padding to times of 8 length
	 * according to PKCS5 padding algorithm.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be encryped.
	 * @param   mode  The DES mode, C for CBC; others for ECB.
	 * @return  The encrypted data byte array
	 */
	public static byte[] encryptData(byte[] key, byte[] data, char mode) {
		// Append data to time of 8 by fill n's n
		int len = (data.length/8) * 8 + 8;
		byte val = (byte)(len - data.length);
		byte[] blocks = new byte[len];
		for(int i=0; i<data.length; i++) blocks[i] = data[i];
		for(int i=data.length; i<len; i++) blocks[i] = val;;

		// Encrypt data in given mode
		return encrypt(key, blocks, mode);
	}

	/**
	 * Decrypt data using DES key in ECB mode.
	 * The key must be a  byte array in 8/16/24 length.
	 * The data to be decrypted must be in times of 8 length.
	 * The returned decrypted data will truncate padding bytes when encrypted
	 * according to PKCS5 padding algorithm.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be decryped.
	 * @return  The decrypted data byte array
	 */

	public static String decryptData(String sKey, String sData) {
		if (sKey != null && sData != null){
			if (!sKey.equals("") && !sData.equals("")){ 
		        return bytestoString(decryptData(sKey.getBytes(), fromHexString(sData)));	
	       	}else{
				return sData;
			}    	
		}else{
			return "";
		}    	    	
	}
	 
	public static byte[] decryptData(byte[] key, byte[] data) {
		// ECB mode
		return decryptData(key, data, 'E');
	}

	/**
	 * Decrypt data using DES key in given mode.
	 * The key must be a  byte array in 8/16/24 length.
	 * The data to be decrypted must be in times of 8 length.
	 * The returned decrypted data will truncate padded bytes when encrypted
	 * according to PKCS5 padding algorithm.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be decryped.
	 * @param   mode  The DES mode, C for CBC; others for ECB.
	 * @return  The decrypted data byte array
	 */
	public static byte[] decryptData(byte[] key, byte[] data, char mode) {
		// Decrypt data in given mode
		byte[] blocks = decrypt(key, data, mode);
		if(blocks == null) return null;
		
		// Check is correct padding
		byte last = blocks[blocks.length-1];
		for(int i=0; i < last; i++) {
			if(blocks[blocks.length-1-i] != last) return blocks;
		}
		
		// Truncate tailing n's n
		int len = blocks.length - last;
		byte[] decData = new byte[len];
		for(int i=0; i<decData.length; i++) decData[i] = blocks[i];
		return decData;
	}

	/**
	 * Encrypt data using DES key in ECB mode.
	 * The key must be a  byte array in 8/16/24 length.
	 * The data to be encrypted must be in times of 8 length.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be encryped.
	 * @return  The encrypted data byte array
	 */
	public static byte[] encrypt(byte[] key, byte[] data) {
		// ECB mode
		return encrypt(key, data, 'E');
	}
	
	/**
	 * Encrypt data using DES key in given mode.
	 * The key must be a  byte array in 8/16/24 length.
	 * The data to be encrypted must be in times of 8 length.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be encryped.
	 * @param   mode  The DES mode, C for CBC; others for ECB.
	 * @return  The encrypted data byte array
	 */
	public static byte[] encrypt(byte[] key, byte[] data, char mode) {
		if(!checkLength(key, data)) return null;
		if(mode == 'C') {
			// CBC mode, encrypt
			return processCBC(key, data, null_icv, 'E');
		} else {
			// ECB mode, encrypt
			return processECB(key, data, 'E');
		}
	}
	
	/**
	 * Decrypt data using DES key in ECB mode.
	 * The key must be a  byte array in 8/16/24 length.
	 * The data to be decrypted must be in times of 8 length.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be decryped.
	 *
	 * @return  The decrypted data byte array
	 */
	public static byte[] decrypt(byte[] key, byte[] data) {
		// ECB mode
		return decrypt(key, data, 'E');
	}

	/**
	 * Decrypt data using DES key in given mode.
	 * The key must be a  byte array in 8/16/24 length.
	 * The data to be decrypted must be in times of 8 length.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data to be decryped.
	 * @param   mode  The DES mode, C for CBC; others for ECB.
	 * @return  The decrypted data byte array
	 */
	public static byte[] decrypt(byte[] key, byte[] data, char mode) {
		if(!checkLength(key, data)) return null;
		if(mode == 'C') {
			// CBC mode, decrypt
			return processCBC(key, data, null_icv, 'D');
		} else {
			// ECB mode, decrypt
			return processECB(key, data, 'D');
		}
	}
	
	/**
	 * Generate MAC value for input data.
	 * The key must be a  byte array in 8/16/24 length.
	 *
	 * @param   key   DES/DES2/DES3 key value.
	 * @param   data  The data for generate MAC.
	 * @param   icv   The initial control vector.
	 * @return  The 16 bytes MAC byte array
	 */
	public static byte[] generateMAC(byte[] key, byte[] data, byte[] icv) {
		// Append data to time of 8 by fill 0x00
		byte[] blocks = null;
		if((data.length % 8) == 0) {
			blocks = data;
		} else {
			int len = (data.length/8) * 8 + 8;
			blocks = new byte[len];
			for(int i=0; i<data.length; i++) blocks[i] = data[i];
			for(int i=data.length; i<len; i++) blocks[i] = 0;
		}

		// Generate mac by DES encrypt in CBC mode
		byte[] encData = processCBC(key, blocks, icv, 'E');

		// Return the last block(MAC value)
		byte[] mac = new byte[8];
		for(int i=0; i < 8; i++) mac[i] = encData[encData.length - 8 + i];
		return mac;
	}

	
	// Encrypt/decrypt in ECB mode 
	private static byte[] processECB(byte[] key, byte[] data, char act) {
		// Processing
		byte[] result = new byte[data.length];
		byte[] source = new byte[8];
		byte[] target = new byte[8];
		if(key.length == 8) {	// DES
			// Process each blcoks
			for(int i=0; i<data.length; i+=8) {
				// Set source
				for(int j=0; j<8; j++) source[j] = data[i+j];
				// Encrypt/Decrypt 8 bytes
				if(act == 'E') {
					// Encrypt
					des('E', key, source, target);
				} else {
					// Decrypt
					des('D', key, source, target);
				}
				// Set result
				for(int j=0; j<8; j++) result[i+j] = target[j];
			}
		} else {	// Triple-DES
			// Setup EDE keys
			byte[] key1 = new byte[8];
			byte[] key2 = new byte[8];
			byte[] key3 = new byte[8];
			setupTriKey(key, key1, key2, key3);
			// Process each blcoks
			byte[] temp = new byte[8];
			for(int i=0; i<data.length; i+=8) {
				// Set source
				for(int j=0; j<8; j++) source[j] = data[i+j];
				// Encrypt/Decrypt 8 bytes
				if(act == 'E') {
					// Encrypt
					des('E', key1, source, target);
					des('D', key2, target, temp);
					des('E', key3, temp, target);
				} else {
					// Decrypt
					des('D', key1, source, target);
					des('E', key2, target, temp);
					des('D', key3, temp, target);
				}
				// Set result
				for(int j=0; j<8; j++) result[i+j] = target[j];
			}
		}
		// Return result
		return result;
	}
	
	// Encrypt/decrypt in CBC mode 
	private static byte[] processCBC(byte[] key, byte[] data, byte[] icv, char act) {
		// Processing
		byte[] result = new byte[data.length];
		byte[] source = new byte[8];
		byte[] target = new byte[8];
		byte[] temp = new byte[8];
		if(key.length == 8) {	// DES
			if(act == 'E') {	// Encrypt
				// First block
				for(int j=0; j<8; j++) source[j] = icv[j];
				// Process each blcoks
				for(int i=0; i<data.length; i+=8) {
					// Set source - exclusive OR previous block
					for(int j=0; j<8; j++) source[j] ^= data[i+j];
					// Encrypt 8 bytes
					des('E', key, source, target);
					// Set result
					for(int j=0; j<8; j++) result[i+j] = target[j];
					// Next block
					for(int j=0; j<8; j++) source[j] = target[j];
				}
			} else {	// Decrypt
				// Process each blcoks
				for(int i=0; i < data.length; i+=8) {
					// Set source
					for(int j=0; j<8; j++) source[j] = data[data.length-8-i+j];
					// Decrypt 8 bytes
					des('D', key, source, target);
					// Set target - exclusive OR previous block
					if(i < data.length - 8) {
						for(int j=0; j<8; j++) target[j] ^= data[data.length-16-i+j];
					} else {	// First block
						for(int j=0; j<8; j++) target[j] ^= icv[j];
					}
					// Set result
					for(int j=0; j<8; j++) result[data.length-8-i+j] = target[j];
				}
			}
		} else {	// Triple-DES
			// Setup EDE keys
			byte[] key1 = new byte[8];
			byte[] key2 = new byte[8];
			byte[] key3 = new byte[8];
			setupTriKey(key, key1, key2, key3);
			if(act == 'E') {	// Encrypt
				// First block
				for(int j=0; j<8; j++) source[j] = icv[j];
				// Process each blcoks
				for(int i=0; i<data.length; i+=8) {
					// Set source - exclusive OR previous block
					for(int j=0; j<8; j++) source[j] ^= data[i+j];
					// Encrypt 8 bytes
					des('E', key1, source, target);
					des('D', key2, target, temp);
					des('E', key3, temp, target);
					// Set result
					for(int j=0; j<8; j++) result[i+j] = target[j];
					// Next block
					for(int j=0; j<8; j++) source[j] = target[j];
				}
			} else {	// Decrypt
				// Process each blcoks
				for(int i=0; i<data.length; i+=8) {
					// Set source
					for(int j=0; j<8; j++) source[j] = data[data.length-8-i+j];
					// Decrypt 8 bytes
					des('D', key1, source, target);
					des('E', key2, target, temp);
					des('D', key3, temp, target);
					if(i < data.length - 8) {
						for(int j=0; j<8; j++) target[j] ^= data[data.length-16-i+j];
					} else {	// First block
						for(int j=0; j<8; j++) target[j] ^= icv[j];
					}
					// Set result
					for(int j=0; j<8; j++) result[data.length-8-i+j] = target[j];
				}
			}
		}
		// Return result
		return result;
	}
	
	
	// Check key & data length
	private static boolean checkLength(byte[] key, byte[] data) {
		// 8 bytes for DES, 16 bytes for DES2, 24 bytes for DES3
		if( (key.length != 8) && (key.length != 16)
			&& (key.length != 24) ) return false;
		// Check is data the times of 8 bytes
		if((data.length % 8) != 0) return false;
		// OK
		return true;
	}
	
	// Setup Triple DES keys
	private static void setupTriKey(byte[] key, byte[] key1, byte[] key2, byte[] key3) {
		if(key.length == 16) {
			for(int i=0; i<8; i++) key1[i] = key[i];
			for(int i=0; i<8; i++) key2[i] = key[8+i];
			for(int i=0; i<8; i++) key3[i] = key[i];
		} else if(key.length == 24) {
			for(int i=0; i<8; i++) key1[i] = key[i];
			for(int i=0; i<8; i++) key2[i] = key[8+i];
			for(int i=0; i<8; i++) key3[i] = key[16+i];
		}
	}
	
	// Generate DES of 8 bytes block
	private static void des(char act, byte[] key, byte[] data, byte[] edata) {
		byte[][] key_k	= new byte[16][48];
		byte[] key_bit	= new byte[64];
		byte[] data_bit	= new byte[64];
		byte[] data_lbit= new byte[32];
		byte[] data_rbit= new byte[32];
		byte[] frk_bit	= new byte[32];
		byte[] tmp_bit	= new byte[64];
		//
		spilt_bit(key, 8, key_bit);
		spilt_bit(data, 8, data_bit);
		key_calculation(key_bit, key_k);
		for(int i=0;i<32;i++) {
			data_lbit[i] = data_bit[des_ip[i]-1];
			data_rbit[i] = data_bit[des_ip[i+32]-1];
		}
		//
		if(act == 'E') {
			// encrypt data
			for(int i=0; i<16; i++) {  /* L' = R, R' = L xor f(R,Kn) */ 
				for(int j=0; j<32; j++) tmp_bit[j] = data_rbit[j];
				f_cipher(data_rbit, key_k[i], frk_bit);
				bit_xor(data_lbit, frk_bit, 32, data_rbit);
				for(int j=0; j<32; j++) data_lbit[j] = tmp_bit[j];
			}
		} else {
			// decrypt data
			for(int i=15; i>=0; i--) {  /* L' = R, R' = L xor f(R,Kn) */ 
				for(int j=0; j<32; j++) tmp_bit[j] = data_rbit[j];
				f_cipher(data_rbit, key_k[i], frk_bit);
				bit_xor(data_lbit, frk_bit, 32, data_rbit);
				for(int j=0; j<32; j++) data_lbit[j] = tmp_bit[j];
			}
		}
		//
		for(int i=0; i<32; i++) {
			tmp_bit[i]    = data_rbit[i];
			tmp_bit[i+32] = data_lbit[i];
		}
		// inverse initial perm
		for(int i=0; i<64; i++) data_bit[i] = tmp_bit[des_rip[i]-1];
		merge_bit(data_bit, 8, edata);
	}
	
	// Calculate key
	private static void key_calculation(byte[] keybit, byte[][] key_k) {
		byte[] key_cd = new byte[56];
		// permuted choice 1
		for(int i=0;i<56;i++) key_cd[i] = keybit[des_pc1[i]-1];
		for(int i=0;i<16;i++) {
			// left shift
			left_shift(key_cd, des_lshift[i], 0);  
			left_shift(key_cd, des_lshift[i], 28);
			// permuted choice 2
			for(int j=0;j<48;j++) key_k[i][j] = key_cd[des_pc2[j]-1];
		}
	}
	// Left shift
	private static void left_shift(byte[] data, byte shift, int start) {
		byte[] tmp_bit = new byte[28];
		for(int i=0;i<shift;i++) tmp_bit[i] = data[start+i];
		for(int i=0;i<28-shift;i++) data[start+i] = data[start+i+shift];
		for(int i=0;i<shift;i++) data[start+28-shift+i] = tmp_bit[i];
	}
	// f_cipher
	private static void f_cipher(byte[] rbit, byte[] kbit, byte[] frk) {
		byte[] erbit	= new byte[48];
		byte[] tmp_bit	= new byte[48];
		byte[] key_b	= new byte[8];
		byte[] key_sb	= new byte[8];
		byte[] tmp		= new byte[8];
		byte	row, col;
		// E bit-selection
		for(int i=0;i<48;i++) erbit[i] = rbit[des_e[i]-1];
		bit_xor(erbit, kbit, 48, tmp_bit);
		for(int i=0;i<8;i++) {
			for(int j=0;j<6;j++) key_b[j] = tmp_bit[i*6+j];
			row = (byte)(key_b[0] * 2 + key_b[5]);
			col = (byte)(key_b[1] * 8 + key_b[2] * 4 + key_b[3] * 2 + key_b[4]);
			key_sb[i] = des_s[i][row][col];
		}
		for(int i=0;i<4;i++) tmp[i] = (byte)(key_sb[i*2] * 16 + key_sb[i*2+1]);
		spilt_bit(tmp, 4, tmp_bit);
		// primitive function P
		for(int i=0;i<32;i++) frk[i] = tmp_bit[des_p[i]-1];
	}
	// Split to bit
	private static void spilt_bit(byte[] data, int len, byte[] bit) {
		for(int i=0;i<len;i++) {
			byte ch = data[i];
			for(int j=0;j<8;j++) {
				if((ch & 0x80) != 0) bit[i*8+j] = 1;
				else bit[i*8+j] = 0;
				ch <<= 1;
			}
		}
	}
	// Merge to byte
	private static void merge_bit(byte[] bit, int len, byte[] data) {
		for(int i=0;i<len;i++) {
			data[i] = 0;
			for(int j=0;j<8;j++) {
				data[i] <<= 1;
				data[i] += bit[i*8+j];
			}
		}
	}
	// Exclusive OR
	private static void bit_xor(byte[] a, byte[] b, int len, byte[] ab) {
		for(int i=0;i<len;i++) { 
			if(a[i] == b[i]) ab[i] = 0;
			else ab[i] = 1;
		}
	}
	
	// Null initial control vector
	private static final byte null_icv[] = {   
		0, 0, 0, 0, 0, 0, 0, 0
	};
	// Initial permutation - [64]
	private static final byte des_ip[] = {   
		58, 50, 42, 34, 26, 18, 10, 2,
		60, 52, 44, 36, 28, 20, 12, 4,
		62, 54, 46, 38, 30, 22, 14, 6,
		64, 56, 48, 40, 32, 24, 16, 8,
		57, 49, 41, 33, 25, 17,  9, 1,
		59, 51, 43, 35, 27, 19, 11, 3,
		61, 53, 45, 37, 29, 21, 13, 5,
		63, 55, 47, 39, 31, 23, 15, 7
	};
	// Inverse of the initial permutation - [64]
	private static final byte des_rip[] = {
		40, 8, 48, 16, 56, 24, 64, 32,
		39, 7, 47, 15, 55, 23, 63, 31,
		38, 6, 46, 14, 54, 22, 62, 30,
		37, 5, 45, 13, 53, 21, 61, 29,
		36, 4, 44, 12, 52, 20, 60, 28,
		35, 3, 43, 11, 51, 19, 59, 27,
		34, 2, 42, 10, 50, 18, 58, 26,
		33, 1, 41,  9, 49, 17, 57, 25
	};
	// E bit-selection table - [64]
	private static final byte des_e[] = {
		32,  1,  2,  3,  4,  5,
		 4,  5,  6,  7,  8,  9,
		 8,  9, 10, 11, 12, 13,
		12, 13, 14, 15, 16, 17,
		16, 17, 18, 19, 20, 21,
		20, 21, 22, 23, 24, 25,
		24, 25, 26, 27, 28, 29,
		28, 29, 30, 31, 32,  1
	};
	// Primitive functions s - [8][4][16]
	private static final byte des_s[][][] = {
	   {{14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7},
	    { 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8},
	    { 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0},
	    {15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13}},
	   {{15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10},
	    { 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5},
	    { 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15},
	    {13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9}},
	   {{10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8},
	    {13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1},
	    {13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7},
	    { 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12}},
	   {{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15},
	    {13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9},
	    {10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4},
	    { 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14}},
	   {{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9},
	    {14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6},
	    { 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14},
	    {11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3}},
	   {{12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11},
	    {10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8},
	    { 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6},
	    { 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13}},
	   {{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1},
	    {13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6},
	    { 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2},
	    { 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12}},
	   {{13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7},
	    { 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2},
	    { 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8},
	    { 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11}}
	};
	// Primitive function p - [32]
	private static final byte des_p[] = {
		16,  7, 20, 21,
		29, 12, 28, 17,
		 1, 15, 23, 26,
		 5, 18, 31, 10,
		 2,  8, 24, 14,
		32, 27,  3,  9,
		19, 13, 30,  6,
		22, 11,  4, 25
	};
	// Permuted choice 1 - [56]
	private static final byte des_pc1[] = {
		57, 49, 41, 33, 25, 17,  9,
		 1, 58, 50, 42, 34, 26, 18,
		10,  2, 59, 51, 43, 35, 27,
		19, 11,  3, 60, 52, 44, 36,
		63, 55, 47, 39, 31, 23, 15,
		 7, 62, 54, 46, 38, 30, 22,
		14,  6, 61, 53, 45, 37, 29,
		21, 13,  5, 28, 20, 12,  4
	};
	// Permuted choice 2 - [48]
	private static final byte des_pc2[] = {
		14, 17, 11, 24,  1,  5,
		 3, 28, 15,  6, 21, 10,
		23, 19, 12,  4, 26,  8,
		16,  7, 27, 20, 13,  2,
		41, 52, 31, 37, 47, 55,
		30, 40, 51, 45, 33, 48,
		44, 49, 39, 56, 34, 53,
		46, 42, 50, 36, 29, 32
	};
	// Iteration left shifts - [16]
	private static final byte des_lshift[] = {
		1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
	};
	
	private static String toHexString(byte[] in){
        BigInteger temp = new BigInteger(in);
        return temp.toString(16);
    }
  
    private static byte[] fromHexString(String in){
		BigInteger temp = new BigInteger(in, 16);
		return temp.toByteArray();
	}
	
	private static String bytestoString(byte[] in){
	   String sLine = "";	
	   for (int i = 0; i < in.length; i++) {
           String tmp = new String(new byte[] {in[i]});
           sLine += tmp;
       } 
       return sLine;	
    }
}